package org.example.springbootpra1.demos.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.util.ListUtils;
import com.alibaba.excel.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.example.springbootpra1.demos.bean.ChargeAccountRule;
import org.example.springbootpra1.demos.services.service.ChargeAccountRuleService;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Pattern;

@Slf4j
public class ChargeAccountRuleListener extends AnalysisEventListener<ChargeAccountRule> {

    /**
     * 每隔5条存储数据库，实际使用中可以100条，然后清理list ，方便内存回收
     */
    private static final int BATCH_COUNT = 100;

    /**
     * 创建一个Pattern对象，使用正则表达式校验手机号格式
     */
    private static final Pattern PHONE_REGEX = Pattern.compile("^1[0-9]{10}$");

    /**
     * 缓存的数据
     */
    private List<ChargeAccountRule> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

    /**
     * 错误信息列表
     */
    private final List<String> errorMsgList = new ArrayList<>(BATCH_COUNT);

    private final ChargeAccountRuleService chargeAccountRuleService;

    public ChargeAccountRuleListener(ChargeAccountRuleService chargeAccountRuleService) {
        this.chargeAccountRuleService = chargeAccountRuleService;
    }

    @Override
    public void invoke(ChargeAccountRule chargeAccountRule, AnalysisContext analysisContext) {
        log.info("解析到一条数据:{}", chargeAccountRule);
        int rowIndex = analysisContext.readRowHolder().getRowIndex();
        String name = chargeAccountRule.getRuleName();

        // 只有全部校验通过的对象才能被添加到下一步
        if (nameValid(rowIndex, name)) {
            cachedDataList.add(chargeAccountRule);
        }
        // 达到BATCH_COUNT了，需要去存储一次数据库，防止数据几万条数据在内存，容易OOM
        if (cachedDataList.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        log.info("所有数据解析完成！全部校验通过的数据有{}条", cachedDataList.size());
        // 这里也要保存数据，确保最后遗留的数据也存储到数据库saveData();
        saveData();
    }

    @Override
    public void onException(Exception exception, AnalysisContext context) throws Exception {
        if (exception instanceof RuntimeException) {
            throw exception;
        }
        int index = context.readRowHolder().getRowIndex() + 1;
        errorMsgList.add("第" + index + "行解析错误");
    }

    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        int totalRows = context.readSheetHolder().getApproximateTotalRowNumber() - 1;
        int maxNum = 2000;
        if (totalRows > maxNum) {
            errorMsgList.add("数据量过大,单次最多上传2000条");
            throw new RuntimeException("数据量过大,单次最多上传2000条");
        }
    }

    public List<String> getErrorMsgList() {
        return errorMsgList;
    }

    /**
     * 名称的校验
     *
     * @param rowIndex 行数
     * @param name     名称
     */
    private Boolean nameValid(Integer rowIndex, String name) {
        if (StringUtils.isBlank(name)) {
            errorMsgList.add("第" + rowIndex + "行,'姓名'不能为空");
            return Boolean.FALSE;
        }
        return Boolean.TRUE;
    }

    /**
     * 保存数据到数据库
     */
    private void saveData() {
        if (!cachedDataList.isEmpty()) {
            chargeAccountRuleService.saveBatch(cachedDataList, 100);
        }
    }
}
